var UCD = UCD || {Core:jQuery};
(function(ucd,$)
{
		// var COLOR = ["#fe4365","#fc9c99","#f9d9ad","#d4d4a9","#83af9b"];
		var COLOR;
		var id = 0;
		var marginTop = 18;
		var defaultOptions =
		{
			width: 620,
			height: 240,
			color: ['#75c5db', '#71a6cf', '#e08566', '#00ab76', '#d299d0', '#65d1d0', '#306897']
		}

		function Stack(container, options)
		{	
			this.$container = $(container);
			this.container = document.createElement("div");
			this.$container.append(this.container);
			this.container.setAttribute('id', 'stack_' + id++);
			this.owner = new UCD.MyD3();
			this.owner.container(this.container);
			this.owner.css('white-space', 'nowrap');
			this.options = $.extend({}, defaultOptions, options);
		}
		var proto = Stack.prototype;

		proto.init = function()
		{
			var opts = this.options;
			COLOR = opts.color;
			
			this.svg = this.owner.append('svg')
					.attr('height', opts.height)
					.attr('width', opts.width)
					.attr('overflow', 'hidden');
			this.draw();
			// this.dealEnd();
			this._bindEvents();
		}

		proto.update = function(options)
		{
			this.clear();
			this.setOptions(options);
			this.init();
		}

		proto.draw = function()
		{
			this.rootInit(this.options.json);
		}

		proto.resize = function()
		{
			var width = window.innerWidth;
			var limit = 1200;
			if (width > limit)		
			{
				this.options.width = width / 2;
				this.options.height = this.options.width / 1.78 ;
			}
			this.clear();
			this.init();
		}

		proto.setOptions = function(options)
		{
			this.options = $.extend({}, this.options, options);
		}

		proto.clear =function()
		{
			this._unbindEvents();
			$(this.container).empty();
			this.svg.clear();
			this.svg = null;
		}

		proto.destroy = function()
		{
			this._unbindEvents();	//要先解事件绑定
			$(this.container).remove();
			this.$container = null;
			this.container = null;
			this.svg.clear();
			this.svg = null;
			this.options = null;
			this.owner = null;
		}

		proto.zoom = 
		function zoom(rect) 
		{ 		
			 // var posY = rect.y * (1-percent);
			 // var nowHeight = rect.height + (height - rect.height) * percent;
			 // console.log(this);		this是window
			 var parent = rect.parent;
			 var root = parent.parent;
			 var domainX = rect.parent.x;
			 var domainY = rect.parent.y;
			 var width = this.options.width;
			 var height = this.options.height;

			 if(root.progress && !parent.timerId)
			 {
			 	return;
			 }

			 if(root.progress && parent.timerId)
			 {
			 	clearInterval(parent.timerId);
			 }

			 if(parent.hasZoomed)
			 {
			 	// var d.tmpWidth;	需要一个中间变量来存储各node的缩小时的当前大小的信息
			 	// var d.tmpHeight;
			 	// var d.tmpX;
			 	// var d.tmpY; 
			 	parent.hasZoomed = false;	//缩小
				rect.animationOptions = 
				{
				      duration: 400,
				      onProgress: function(percent) 
				      {
					      root.attrAllChildren('transform', function(d) 
					      { 			//移动g
					      	// console.log(d);
					      	return "translate("+ (d.curX - (d.curX - d.x) * percent) + ' ' + (d.curY - (d.curY - d.y) * percent) +' )';
					      });

					      parent.filter(function(d) { if(d.text) return true;}).attrAllChildren('width', function(d) 
					      { 
					      	// d.curWidth = d.curWidth - (d.curWidth - d.width) * percent;		//另一种动画效果
					      	// return d.curWidth;
					      	d.tmpWidth = d.curWidth - (d.curWidth - d.width) * percent;		
					      	return d.tmpWidth;
					      }).attrAllChildren('height', function(d) 
					      { 
					      	// d.curHeight = d.curHeight - (d.curHeight - d.height) * percent;
					      	// return d.curHeight;
					      	d.tmpHeight = d.curHeight - (d.curHeight - d.height) * percent;
					      	return d.tmpHeight;
					      }).attrAllChildren('transform', function(d) 
					      { 
					      	d.tmpX =  d.curX - (d.curX - d.x) * percent;
				        		d.tmpY = d.curY - (d.curY - d.y) * percent;
				        		var text = d.text;
					       	text.attr('x', d.tmpX + d.tmpWidth / 2).attr('y', d.tmpY + d.height / 2 - marginTop);
					       	text.t1.attr('x', text.x);
					       	text.t2.attr('x', text.x);
					        	return 'translate(' + d.tmpX + ' ' + d.tmpY + ' )';
					      });
				      }, 
				      onComplete: function(percent) 
				      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
					      
					        
					      root.attrAllChildren('transform', function(d) 
					      { 			//移动g
						      if(d != parent) return "translate("+ d.x + ' '+ d.y + '  )';
						      return 'translate(' + d.x + ' ' + d.y + ' )';
					      });

					      parent.filter(function(d) { if(d.text) return true;}).attrAllChildren('width', function(d) 
					      { 
					      	d.tmpWidth = d.width;
					      	return d.tmpWidth
					      }).attrAllChildren('height', function(d) 
					      { 
					      	d.tmpHeight = d.height;
					      	return d.tmpHeight
					      }).attrAllChildren('transform', function(d) 
					      { 
					      	d.tmpX =  d.x ;	//对平移效果进行了一些修正
				        		d.tmpY =d.y;
				        		var text = d.text;
					       	text.attr('x', d.tmpX + d.tmpWidth / 2).attr('y', d.tmpY + d.height / 2 - marginTop);
					       	text.t1.attr('x', text.x);
					       	text.t2.attr('x', text.x);
					        	return 'translate(' + d.tmpX + ' ' + d.tmpY + ' )';
					      });	
					      root.progress = false;	
				      }
				};
			}
			else
			{
				parent.hasZoomed = true;
				rect.animationOptions = 
				{
				      duration: 400,
				      onProgress: function(percent) 
				      {
				        // console.log(rect.height);
					        // console.log(root);
					      root.attrAllChildren('transform', function(d) 		//对g进行操作
					      { 
						        if(d != parent) 		//不是正在操作的节点
						        {	
						        		d.curY = d.y;
						        		d.curX = d.x;
						        		if(d.y - domainY > 0)
					        			{
					        				d.finalY = height;
					        				d.curY = d.y + (d.finalY - d.y) * percent;
					        			}else if(d.y - domainY < 0)
					        			{
					        				d.curY = d.y - parent.y * percent;
					        			}
					        			if(d.x - domainX > 0)
						        		{
						        			d.curX = d.x + (width - d.x) * percent;
						        		}else if(d.x - domainX < 0)
						        		{
						        			d.curX = d.x - parent.x * percent;
						        		}
						        		return "translate("+ d.curX + ' ' + d.curY +' )';
						        }
						        		d.curX = d.x * (1-percent);
						        		d.curY = d.y * (1 - percent);
						        		// console.log("x:"+ d.x + "	y:"+d.y);
						        		return 'translate(' + d.curX + ' ' + d.curY + ' )';
					        });

					      parent.filter( function(d) { if(d.text) return true;}).attrAllChildren('transform', function(d) 		//对子节点进行操作
					      {  						        
				        		d.curX =  d.x  + (d.x  * (width) / (parent.width ) - d.x) * percent ;		//对平移效果进行了一些修正
				        		d.curY = d.y + (d.y * (height) / (parent.height ) - d.y) * percent;
				        		// console.log("x:"+ d.x + "	y:"+d.y);
					        		return 'translate(' + d.curX + ' ' + d.curY + ' )';
					       }).attrAllChildren('width', function(d)
					       {
					       	d.curWidth = (d.width + 1)  + ( (width) / (parent.width ) * (d.width + 1) - (d.width + 1) ) * percent - 1;
					       	return d.curWidth ;
					       }).attrAllChildren('height', function(d)
					       {
					       	d.curHeight = (d.height + 1)  + ( (height / (parent.height ) ) * (d.height + 1) - (d.height + 1) ) * percent - 1;
					       	var text = d.text;
					       	text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.height / 2 - marginTop);
					       	text.t1.attr('x', text.x);
					       	text.t2.attr('x', text.x);
					       	return d.curHeight ;
					       });

					      // console.log(parent);
					      // console.log("end\n");
				        		
				      }, 
				      onComplete: function(percent) 
				      {		//结束时函数，这里要做统一的初始化，不然由于时刻划分问题会有细微的差距
					      root.attrAllChildren('transform', function(d) 
					      { 
						      if(d != parent) 
						      {	
						      		if(d.y - domainY > 0)
					        			{
					        				d.curY = height ;
					        			}else if(d.y - domainY < 0)
					        			{
					        				d.curY = d.y - parent.y;
					        			}
								if(d.x - domainX > 0)
							        	{
							        		d.curX = width;
							        	}else if(d.x - domainX < 0) 
							        	{
							        		d.curX = d.x - parent.x ;
							        	}	
						        		return "translate("+ d.curX + ' ' + d.curY +' )';
						        		
						      } 
						        		return 'translate(' + 0 +' 0 )';
					      });

					      parent.filter( function(d) { if( d.text ) return true;}).attrAllChildren('transform', function(d) 		//对子节点进行操作
					      {  		
					     	// console.log(d.x + ' ' + d.y);	        
				        		d.curX = d.x * (width)  / (parent.width) ;
				        		d.curY =  d.y * (height)  / (parent.height);
				        		// console.log("x:"+ d.x + "	y:"+d.y);
					        	return 'translate(' + d.curX + ' ' + d.curY + ' )';
					        	// return "translate("+ d.curX + ' ' + d.curY +' )';
					       }).attrAllChildren('width', function(d)
					       {
					       	d.curWidth =  (width) / (parent.width) * (d.width + 1) - 1 ;
					       	return d.curWidth;
					       }).attrAllChildren('height', function(d)
					       {
					       	d.curHeight = (height ) / (parent.height ) * (d.height + 1) - 1;
					       	var text = d.text;
					       	text.attr('x', d.curX + d.curWidth / 2).attr('y', d.curY + d.height / 2 - marginTop);
					       	text.t1.attr('x', text.x);
					       	text.t2.attr('x', text.x);
					       	return d.curHeight;
					       });
					       root.progress = false;
				   }
				};

			}

			root.progress = true;
			// console.log(this.owner);
		   	parent.timerId = this.owner.tool.animate(rect.animationOptions);   //设置动画时间间隔，并调用onProgress等函数进行重绘

			return this;

		}

		proto._bindEvents = 
		function _bindEvents()
		{
			var _this = this;
			// _this = this;		向这样的变量是挂在window上，在第二次触发事件时就会被回收，我也不知道为什么
			$(_this.svg.owner).on("mousedown", "rect", function(e){
				// console.log(_this);
				_this.zoom(this.d3);
			});

			$(_this.svg.owner).on("mousedown", "text", function(e){
				// console.log(this);
				_this.zoom(this.rect);
			});

		}

		proto._unbindEvents = function()
		{
			$(this.svg.owner).off("mousedown");
		}

		proto.rootInit = function(root)
		{
			var k = 10000;
			var remainSize = 1 * k;
			var opts = this.options;
			var children = root.children;
			var sum = 0;
			var endIndex = 0;
			var startIndex = 0;
			var svg = this.svg;
			var rect;
			var width = 0;
			var height = 0;
			var h = 0;
			var w = 0;
			var translateX = 0;
			var translateY = 0;
			var curWidth = opts.width;
			var curHeight = opts.height;
			var tmpX = 0;
			var tmpY = 0;
			var percentOfRemain = 0;
			var g;
			// var curNode;

			// for(var i = 0 ; i < children.length ; i++)		如果父节点没有size，累加子节点size
			// {
			// 	curNode = children[i].children;
			// 	for(var j = 0 ; j < curNode.length ; j++)
			// 	{
			// 		sum += curNode[j].size;
			// 		// console.log(sum);
			// 	}
			// 	children[i].size = sum;
			// 	// console.log(sum);			// 	sum = 0;
			// }
			// children.sort(function(a,b) { return b.size - a.size;});	//整数升序排列
			for(var i = 0; i < children.length; i ++)
			{
				children[i].size <= 0 ? children.splice(i,1) : 0;
			}

			while(remainSize > 10)
			{
				// remainSize -= sum;
				sum = 0;

				for(var i = startIndex; i < children.length ; i++)
				{

					sum += children[i].size * k;
					// console.log("sum:" + sum + "	remainSize:" + remainSize);
					percentOfRemain = sum / remainSize;
					endIndex = i;
					break;

				}
				// console.log(sum);
				width = curWidth * percentOfRemain;
				height = curHeight;
				tmpY = translateY = opts.height - curHeight;
				// console.log(sum);
				for(var j = startIndex ; j <= endIndex; j++)
				{
					h = children[j].size * k / sum * height;
					g = svg.append('g') .attr('width', width - 1 ).attr('height', h - 1).attr('fill', COLOR[j % 7])
								  .attr('transform', 'translate(' + translateX + ' ' + tmpY +')').attr('myOpacity', 1);
					g.x = translateX;
					g.y = tmpY;
					this.rectInit(children[j] , g);
					tmpY += h;
				}

				curWidth -= width;
				remainSize -= sum;
				// if(remainSize <= 10 ) break;

				// sum = 0;
				startIndex = endIndex + 1;

				tmpX = translateX = opts.width -curWidth;
				
			}
		}

		function rectSizeInit(node)
		{
			var all = node.size;
			var children = node.children;
			var length = children.length;

			for(var i = 0; i < length; i ++)
			{
				// console.log(children[i]);
				if(children[i].size > 0)
				{
					children[i].size = children[i].size / all;
					// 
				}else
				{
					children.splice(i,1);
					i --;
					length --;
				}
			}
		}

		proto.rectInit = function(node , g)		//增加浮点数运算精度，使用乘以一个系数10000后进行相应运算
		{
			var opts = this.options;
			var k = 10000;
			var remainSize = 1 * k ;
			var children = node.children;
			var sum = 0;
			var endIndex = 0;
			var startIndex = 0;
			var rect;
			var width = 0;
			var height = 0;
			var h = 0;
			var w = 0;
			var translateX = 0;
			var translateY = 0;
			var curWidth = g.width;
			var curHeight = g.height;
			var tmpX = 0;
			var tmpY = 0;
			var percentOfRemain = 0;
			// var curNode;

			// for(var i = 0 ; i < children.length ; i++)		如果父节点没有size，累加子节点size
			// {
			// 	curNode = children[i].children;
			// 	for(var j = 0 ; j < curNode.length ; j++)
			// 	{
			// 		sum += curNode[j].size;
			// 		// console.log(sum);
			// 	}
			// 	children[i].size = sum;
			// 	// console.log(sum);
			// 	sum = 0;
			// }
			children.sort(function(a,b) { return b.size - a.size;});	//整数升序排列
			rectSizeInit(node);

			while(remainSize > 10)
			{
				sum = 0;
				for(var i = startIndex ; i < children.length ; i++)
				{
					sum += children[i].size * k;
					percentOfRemain = sum / remainSize;
					// console.log(children[i].name + ": " + percentOfRemain + " \n remain: " + remainSize);
					// console.log("sum:" + sum + "	remainSize:" + remainSize);
					// console.log(children[i].size);
					if( percentOfRemain > 0.4 * remainSize / k)
					{
						endIndex = i;
						break;
					}
				}

				width = curWidth;
				height = curHeight * percentOfRemain;
				// console.log(sum);
				tmpX = translateX = g.width -curWidth;
				
				for(var j = startIndex ; j <= endIndex; j++)
				{
					w =children[j].size * k / sum * width;
					rect = g.append('rect') .attr('width', w - 1 ).attr('height', height - 1).attr('fill', g.fill)
								  .attr('transform', 'translate(' + tmpX + ' ' + translateY +')').attr('opacity', g.myOpacity);
					g.myOpacity -= 0.15;
					// console.log(rect.height);
					rect.x = tmpX;
					rect.y = translateY;
					rect.curWidth = rect.width;
					rect.curHeight = rect.height;
					rect.owner.d3 = rect;
					text = g.append('text').attr('y', rect.y + rect.height / 2 - marginTop).attr('x', rect.x + rect.width / 2 ).attr('text-anchor', 'middle');
				 	text.owner.rect = rect;
				 	// text.owner.textContent = children[j].name;
				 	text.t1 = text.append('tspan').attr('x', text.x ).attr('dy', opts.height / 10 + 'px');
				 	text.t1.owner.textContent = children[j].name;
				 	// console.log(text.t1);
				 	text.t2 = text.append('tspan').attr('x', text.x ).attr('dy', opts.height / 10 + 'px');
				 	text.t2.owner.textContent = children[j].num;
				 	if(text.t1.owner.offsetWidth + text.t2.owner.offsetWidth < width && text.t1.owner.offsetHeight + text.t2.owner.offsetHeight > height)
				 	{
				 		text.t2.attr('display', 'none');
				 		text.t1.owner.textContent = children[j].name + '	' + children[j].num;
				 		text.t1.attr('dy', opts.height / 9 + 'px');
				 	}	
				 	if(text.t1.owner.offsetWidth > w || text.owner.offsetHeight > height)	
				 		{
				 			text.t1.attr('display', 'none');
				 			text.t2.attr('dy', opts.height / 9 + 'px');
				 		}
				 	if(text.t2.owner.offsetWidth > w || text.t2.owner.offsetHeight > height)	text.t2.attr('display', 'none');
				 	rect.text = text;
					tmpX += w;
				}

				curHeight -= height;
				startIndex = endIndex + 1;
				remainSize -= sum;

				if(remainSize <= 10 ) break;

				sum = 0;
				for(var i = startIndex; i < children.length ; i++)
				{

					sum += children[i].size * k;
					// console.log(children[i].size * k);
					// console.log("sum:" + sum + "	remainSize:" + remainSize);
					percentOfRemain = sum / remainSize;
					// console.log(children[i].name + ": " + percentOfRemain + " \n remain: " + remainSize);
					// console.log(children[i].size);
					if( percentOfRemain > 0.4 * remainSize / k )
					{
						// console.log("sum:" + sum + "	remainSize:" + remainSize);
						endIndex = i;
						break;
					}
				}
				// console.log(sum);
				width = curWidth * percentOfRemain;
				height = curHeight;
				tmpY = translateY = g.height - curHeight;
				// console.log(sum);
				for(var j = startIndex ; j <= endIndex; j++)
				{
					h = children[j].size * k / sum * height ;
					rect = g.append('rect') .attr('width', width - 1 ).attr('height', h - 1).attr('fill', g.fill)
								  .attr('transform', 'translate(' + translateX + ' ' + tmpY +')').attr('opacity', g.myOpacity);
					g.myOpacity -= 0.05;
					rect.x = translateX;
					rect.y = tmpY;
					rect.curWidth = rect.width;
					rect.curHeight = rect.height;
					rect.owner.d3 = rect;
					text = g.append('text').attr('y', rect.y + rect.height / 2 - marginTop).attr('x',rect.x + rect.width / 2 ).attr('text-anchor', 'middle');
				 	text.owner.rect = rect;
				 	// text.owner.textContent = children[j].name;
				 	text.t1 = text.append('tspan').attr('x', text.x ).attr('dy', opts.height / 10 + 'px');
				 	text.t1.owner.textContent = children[j].name;
				 	text.t2 = text.append('tspan').attr('x', text.x ).attr('dy', opts.height / 10 + 'px');
				 	text.t2.owner.textContent = children[j].num;
				 	if(text.t1.owner.offsetWidth + text.t2.owner.offsetWidth < width && text.t1.owner.offsetHeight + text.t2.owner.offsetHeight > height)
				 	{
				 		text.t2.attr('display', 'none');
				 		text.t1.owner.textContent = children[j].name + '	' + children[j].num;
				 		text.t1.attr('dy', opts.height / 9 + 'px');
				 	}
				 	if(text.t1.owner.offsetWidth > width || text.owner.offsetHeight > h)	
				 		{
				 			text.t1.attr('display', 'none');
				 			text.t2.attr('dy', opts.height / 9 + 'px');
				 		}
				 	if(text.t2.owner.offsetWidth > w || text.t2.owner.offsetHeight > height)	text.t2.attr('display', 'none');
				 	rect.text = text;
					tmpY += h;
				}

				curWidth -= width;
				remainSize -= sum;
				// console.log(remainSize);
				
				startIndex = endIndex + 1;


			}

		}
		ucd.Stack = Stack;
})(UCD,UCD.Core);
